<?php
/*
 * Copyright (c) 2008 Sergey Bondari, bondari@bondari.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - The name of the author may not be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

namespace Mosaic\System;

/**
 * Class resource information
 *
 * @package System
 * @subpackage Resources
 */
class ClassResourceInfo extends ResourceInfo {
	/**
	 * Class full name
	 * @var string
	 */
	private $className;

	/**
	 * File URL with class skeleton code, that implements class functionality
	 * @var string
	 */
	private $skeleton;

	/**
	 * File URL with class stub code, that implmenents communication with skeleton instance
	 * @var string
	 */
	private $stub;

	/**
	 * Indicates that class was already loaded
	 * @var boolean
	 */
	private $loaded = false;

	/**
	 * Resource constructor
	 *
	 * @param string Resource URN (mosaic:resource:class)
	 * @param string Name of the class
	 * @param string Class code file name
	 * @param string Stub file name
	 */
	function __construct($systemID, $className, $skelFileName, $stubFileName = null) {
		$this->systemID = $systemID;
		$this->className = $className;
		$this->skeleton = $skelFileName;
		$this->stub = $stubFileName;
	}


	/**
	 * Unique key generator for this resource instance inside the node
	 *
	 * @return string Resource node key
	 */
	protected function calcKey() {
		return self::createKey($this->systemID, $this->className);
	}

	/**
	 * Resource preparation.
	 *
	 * Function that implements prepare() functionality. Loads the class definition into PHP.
	 *
	 * @return void
	 */
	public function prepare() {
		if (!$this->loaded) {
			$this->checkFiles();
			if (!$this->isRemoteObjectClass()) {
				/*
				 * Not a remote object class
				 */
				require_once($this->skeleton);

			} else {
				/*
				 * Remote object class.
				 * Everybody except an object broker gets stub.
				 * Object broker should get skeleton
				 */
				global $sys;
				switch ($sys->role) {
					case OBJECT_BROKER:
						require_once($this->skeleton);
					break;
					default:
						require_once($this->stub);
				}
			}
			$this->loaded = true;
		}
	}

	/**
	 * Function that indicates whether this is a remote class (stub/skeleton model)
	 * @return boolean
	 */
	public function isRemoteObjectClass() {
		return isset($this->stub);
	}

	/**
	 * Function returns content of the stub code to load on client
	 * @return string Stub code
	 */
	public function getStubCode() {
		if (isset($this->stub)) {
			$this->checkFiles();
			return preg_replace('/^\s*<\?(php)?/','',file_get_contents($this->stub));
		} else {
			throw new RuntimeException('This class does not have stub.');
		}
	}

	/**
	 * Function verifies files accessibility and existance
	 * Throws an exception if error
	 * @return void
	 */
	public function checkFiles() {
		if (isset($this->stub) && (!is_file($this->stub) || !is_readable($this->stub))) {
			throw new RuntimeException('Missing or inaccessible stub file '.$this->stub);
		}
		if (!is_file($this->skeleton) || !is_readable($this->skeleton)) {
			throw new RuntimeException('Missing or inaccessible skeleton file '.$this->stub);
		}
	}


	/**
	 * Class name getter
	 * @return string
	 */
	public function getClassName() {
		return $this->className;
	}

}
